Plotly.rs
Plotly.rs is a plotting library powered by Plotly.js. The aim is to bring over to Rust all the functionality that Python users have come to rely on; with the added benefit of type safety and speed.
Plotly.rs is free and open source. You can find the source on GitHub. Issues and feature requests can be posted on the issue tracker.
API Docs
This book is intended to be a recipe index and is complemented by the API documentation.
License
Plotly.rs is distributed under the terms of the MIT license.
See LICENSE-MIT, and COPYRIGHT for details.
Getting Started
To start using Plotly.rs in your project add the following to your Cargo.toml:
[dependencies]
plotly = "0.5.0"
To add the ability to save plots in the following formats: png, jpeg, webp, svg, pdf and eps, you can use the kaleido feature. Previous versions of Plotly.rs used the orca feature; however this has been deprecated as it provided the same functionality but required additional installation steps. To enabel the kaleido feature add the following to your Cargo.toml instead:
[dependencies]
plotly = { version = "0.5.0", features = ["kaleido"] }
Plotly.rs has three main components:
- Traces; these are containers for the data for display,
- Layout, fine tunes the display of traces on the canvas and more generally controls the way that the plot is displayed, and,
- Plot; is the component that brings traces and the layout together to display the plot in either html format or rasterise the resulting view.
All available traces (e.g. Scatter, Bar, Histogram etc), the Layout and Plot have been hoisted in the plotly namespace so that they can be imported simply using the following:
#![allow(unused_variables)] fn main() { use plotly::{Plot, Layout, Scatter}; }
The aforementioned components can be combined to produce as simple plot as follows:
extern crate plotly; use plotly::common::Mode; use plotly::{Plot, Scatter}; fn line_and_scatter_plot() { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17]) .name("trace1") .mode(Mode::Markers); let trace2 = Scatter::new(vec![2, 3, 4, 5], vec![16, 5, 11, 9]) .name("trace2") .mode(Mode::Lines); let trace3 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12]).name("trace3"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.show(); } fn main() -> std::io::Result<()> { line_and_scatter_plot(); Ok(()) }
which results in the following figure:

The above code will generate an html page of the Plot and display it in the default browser. The html for the plot is stored in the platform specific temporary directory. To save the html result the following can be used:
#![allow(unused_variables)] fn main() { plot.to_html("/home/user/line_and_scatter_plot.html"); }
It is often the case that plots are produced to be included in a document and a different format for the plot is desirable (e.g. png, jpeg etc). Given that the html version of the plot is composed of vector graphics, the display when converted to a non-vector format (e.g. png) is not guaranteed to be identical to the one displayed in html. This means that some fine tuning may be required to get to the desired output. To support that iterative workflow the Plot has show_* methods which display the rasterised output to the target format, for example this:
#![allow(unused_variables)] fn main() { plot.show_png(1280, 900); }
will display in the browser the rasterised plot; 1280 pixels wide and 900 pixels tall, in png format. Once a satisfactory result is achieved, and assuming the kaleido feature is enabled, the plot can be saved using the following:
#![allow(unused_variables)] fn main() { plot.save("/home/user/plot_name.ext", ImageFormat::PNG, 1280, 900, 1.0); }
The extension in the file-name path is optional as the appropriate extension (ImageFormat::PNG) will be included. Note that in all functions that save files to disk both relative and absolute paths are supported.
Recipes
Most of the recipes presented here have been adapted from the official documentation for plotly.js. Contributions of interesting plots that showcase the capabilities of the library are most welcome. For more information on the process please see the contributing guidelines.
Basic Charts
| Kind | Link |
|---|---|
| Scatter Plots | ![]() |
| Line Charts | ![]() |
| Bar Charts | ![]() |
Scatter Plots
The following imports have been used to produce the plots below:
#![allow(unused_variables)] fn main() { use plotly::common::{ DashType, ErrorData, ErrorType, Fill, Font, Line, LineShape, Marker, Mode, Title, }; use plotly::layout::{Axis, Layout, Legend, TicksDirection}; use plotly::{NamedColor, Plot, Rgb, Rgba, Scatter}; use rand_distr::{Distribution, Normal}; use itertools; use itertools_num::linspace; }
The to_inline_html method is used to produce the html plot displayed in this page.
Simple Scatter Plot
#![allow(unused_variables)] fn main() { fn simple_scatter_plot(show: bool) { let n: usize = 100; let t: Vec<f64> = linspace(0., 10., n).collect(); let y = t.iter().map(|x| x.sin()).collect(); let trace = Scatter::new(t, y).mode(Mode::Markers); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("simple_scatter_plot"))); } }
Line and Scatter Plots
#![allow(unused_variables)] fn main() { fn line_and_scatter_plots(show: bool) { let n: usize = 100; let mut rng = rand::thread_rng(); let random_x: Vec<f64> = linspace(0., 1., n).collect(); let random_y0: Vec<f64> = Normal::new(5., 1.) .unwrap() .sample_iter(rng) .take(n) .collect(); let random_y1: Vec<f64> = Normal::new(0., 1.) .unwrap() .sample_iter(rng) .take(n) .collect(); let random_y2: Vec<f64> = Normal::new(-5., 1.) .unwrap() .sample_iter(rng) .take(n) .collect(); let trace1 = Scatter::new(random_x.clone(), random_y0) .mode(Mode::Markers) .name("markers"); let trace2 = Scatter::new(random_x.clone(), random_y1) .mode(Mode::LinesMarkers) .name("linex+markers"); let trace3 = Scatter::new(random_x, random_y2) .mode(Mode::Lines) .name("lines"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("line_and_scatter_plots"))); } }
Bubble Scatter Plots
#![allow(unused_variables)] fn main() { fn bubble_scatter_plots(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 11, 12, 13]) .mode(Mode::Markers) .marker( Marker::new() .size_array(vec![40, 60, 80, 100]) .color_array(vec![ NamedColor::Red, NamedColor::Blue, NamedColor::Cyan, NamedColor::OrangeRed, ]), ); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("bubble_scatter_plots"))); } }
Data Labels Hover
#![allow(unused_variables)] fn main() { fn data_labels_hover(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 6, 3, 6, 1]) .mode(Mode::Markers) .name("Team A") .marker(Marker::new().size(12)); let trace2 = Scatter::new(vec![1.5, 2.5, 3.5, 4.5, 5.5], vec![4, 1, 7, 1, 4]) .mode(Mode::Markers) .name("Team B") .marker(Marker::new().size(12)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new() .title(Title::new("Data Labels Hover")) .x_axis(Axis::new().title(Title::new("x")).range(vec![0.75, 5.25])) .y_axis(Axis::new().title(Title::new("y")).range(vec![0., 8.])); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("data_labels_hover"))); } }
Data Labels on the Plot
#![allow(unused_variables)] fn main() { fn data_labels_on_the_plot(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 6, 3, 6, 1]) .mode(Mode::Markers) .name("Team A") .marker(Marker::new().size(12)) .text_array(vec!["A-1", "A-2", "A-3", "A-4", "A-5"]); let trace2 = Scatter::new(vec![1.5, 2.5, 3.5, 4.5, 5.5], vec![4, 1, 7, 1, 4]) .mode(Mode::Markers) .name("Team B") .text_array(vec!["B-a", "B-b", "B-c", "B-d", "B-e"]) .marker(Marker::new().size(12)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new() .title(Title::new("Data Labels on the Plot")) .x_axis(Axis::new().range(vec![0.75, 5.25])) .y_axis(Axis::new().range(vec![0., 8.])); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("data_labels_on_the_plot"))); } }
Colored and Styled Scatter Plot
#![allow(unused_variables)] fn main() { fn colored_and_styled_scatter_plot(show: bool) { let trace1 = Scatter::new(vec![52698, 43117], vec![53, 31]) .mode(Mode::Markers) .name("North America") .text_array(vec!["United States", "Canada"]) .marker( Marker::new() .color(Rgb::new(164, 194, 244)) .size(12) .line(Line::new().color(NamedColor::White).width(0.5)), ); let trace2 = Scatter::new( vec![ 39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007, ], vec![33, 20, 13, 19, 27, 19, 49, 44, 38], ) .mode(Mode::Markers) .name("Europe") .text_array(vec![ "Germany", "Britain", "France", "Spain", "Italy", "Czech Rep.", "Greece", "Poland", ]) .marker(Marker::new().color(Rgb::new(255, 217, 102)).size(12)); let trace3 = Scatter::new( vec![42952, 37037, 33106, 17478, 9813, 5253, 4692, 3899], vec![23, 42, 54, 89, 14, 99, 93, 70], ) .mode(Mode::Markers) .name("Asia/Pacific") .text_array(vec![ "Australia", "Japan", "South Korea", "Malaysia", "China", "Indonesia", "Philippines", "India", ]) .marker(Marker::new().color(Rgb::new(234, 153, 153)).size(12)); let trace4 = Scatter::new( vec![19097, 18601, 15595, 13546, 12026, 7434, 5419], vec![43, 47, 56, 80, 86, 93, 80], ) .mode(Mode::Markers) .name("Latin America") .text_array(vec![ "Chile", "Argentina", "Mexico", "Venezuela", "Venezuela", "El Salvador", "Bolivia", ]) .marker(Marker::new().color(Rgb::new(142, 124, 195)).size(12)); let layout = Layout::new() .title(Title::new("Quarter 1 Growth")) .x_axis( Axis::new() .title(Title::new("GDP per Capita")) .show_grid(false) .zero_line(false), ) .y_axis(Axis::new().title(Title::new("Percent")).show_line(false)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("colored_and_styled_scatter_plot")) ); } }
Large Data Sets
#![allow(unused_variables)] fn main() { fn large_data_sets(show: bool) { let n: usize = 100_000; let mut rng = rand::thread_rng(); let r: Vec<f64> = Uniform::new(0., 1.).sample_iter(rng).take(n).collect(); let theta: Vec<f64> = Normal::new(0., 2. * std::f64::consts::PI) .unwrap() .sample_iter(rng) .take(n) .collect(); let colors: Vec<f64> = Normal::new(0., 1.) .unwrap() .sample_iter(rng) .take(n) .collect(); let x: Vec<f64> = r .iter() .zip(theta.iter()) .map(|args| args.0 * args.1.cos()) .collect(); let y: Vec<f64> = r .iter() .zip(theta.iter()) .map(|args| args.0 * args.1.sin()) .collect(); let trace = Scatter::new(x, y) .open_gl_mode(true) .mode(Mode::Markers) .marker( Marker::new() .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)) .color_array(colors) .line(Line::new().width(1.)), ); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } // Note the following will not show the full output of the `to_inline_html` method. println!("{}", plot.to_inline_html(Some("large_data_sets"))); } }
Line Charts
The following imports have been used to produce the plots below:
#![allow(unused_variables)] fn main() { use plotly::common::{ DashType, ErrorData, ErrorType, Fill, Font, Line, LineShape, Marker, Mode, Title, }; use plotly::layout::{Axis, Layout, Legend, TicksDirection}; use plotly::{NamedColor, Plot, Rgb, Rgba, Scatter}; use rand_distr::{Distribution, Normal}; use itertools; use itertools_num::linspace; }
The to_inline_html method is used to produce the html plot displayed in this page.
Adding Names to Line and Scatter Plot
#![allow(unused_variables)] fn main() { fn adding_names_to_line_and_scatter_plot(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17]) .mode(Mode::Markers) .name("Scatter"); let trace2 = Scatter::new(vec![2, 3, 4, 5], vec![16, 5, 11, 9]) .mode(Mode::Lines) .name("Lines"); let trace3 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12]) .mode(Mode::LinesMarkers) .name("Scatter + Lines"); let layout = Layout::new().title(Title::new("Adding Names to Line and Scatter Plot")); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("adding_names_to_line_and_scatter_plot"))); } }
Line and Scatter Styling
#![allow(unused_variables)] fn main() { fn line_and_scatter_styling(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17]) .mode(Mode::Markers) .name("trace1") .marker(Marker::new().color(Rgb::new(219, 64, 82)).size(12)); let trace2 = Scatter::new(vec![2, 3, 4, 5], vec![16, 5, 11, 9]) .mode(Mode::Lines) .name("trace2") .line(Line::new().color(Rgb::new(55, 128, 191)).width(3.0)); let trace3 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12]) .mode(Mode::LinesMarkers) .name("trace3") .marker(Marker::new().color(Rgb::new(128, 0, 128)).size(12)) .line(Line::new().color(Rgb::new(128, 0, 128)).width(1.0)); let layout = Layout::new().title(Title::new("Line and Scatter Styling")); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("line_and_scatter_styling"))); } }
Styling Line Plot
#![allow(unused_variables)] fn main() { fn styling_line_plot(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17]) .mode(Mode::Markers) .name("Red") .line(Line::new().color(Rgb::new(219, 64, 82)).width(3.0)); let trace2 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12]) .mode(Mode::LinesMarkers) .name("Blue") .line(Line::new().color(Rgb::new(55, 128, 191)).width(1.0)); let layout = Layout::new() .title(Title::new("Styling Line Plot")) .width(500) .height(500); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("styling_line_plot"))); } }
Line Shape Options for Interpolation
#![allow(unused_variables)] fn main() { fn line_shape_options_for_interpolation(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 3, 2, 3, 1]) .mode(Mode::LinesMarkers) .name("linear") .line(Line::new().shape(LineShape::Linear)); let trace2 = Scatter::new(vec![1, 2, 3, 4, 5], vec![6, 8, 7, 8, 6]) .mode(Mode::LinesMarkers) .name("spline") .line(Line::new().shape(LineShape::Spline)); let trace3 = Scatter::new(vec![1, 2, 3, 4, 5], vec![11, 13, 12, 13, 11]) .mode(Mode::LinesMarkers) .name("vhv") .line(Line::new().shape(LineShape::Vhv)); let trace4 = Scatter::new(vec![1, 2, 3, 4, 5], vec![16, 18, 17, 18, 16]) .mode(Mode::LinesMarkers) .name("hvh") .line(Line::new().shape(LineShape::Hvh)); let trace5 = Scatter::new(vec![1, 2, 3, 4, 5], vec![21, 23, 22, 23, 21]) .mode(Mode::LinesMarkers) .name("vh") .line(Line::new().shape(LineShape::Vh)); let trace6 = Scatter::new(vec![1, 2, 3, 4, 5], vec![26, 28, 27, 28, 26]) .mode(Mode::LinesMarkers) .name("hv") .line(Line::new().shape(LineShape::Hv)); let mut plot = Plot::new(); let layout = Layout::new().legend( Legend::new() .y(0.5) .trace_order("reversed") .font(Font::new().size(16)), ); plot.set_layout(layout); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); plot.add_trace(trace5); plot.add_trace(trace6); plot.show_png(1024, 680); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("line_shape_options_for_interpolation"))); } }
Line Dash
#![allow(unused_variables)] fn main() { fn line_dash(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 3, 2, 3, 1]) .mode(Mode::LinesMarkers) .name("solid") .line(Line::new().dash(DashType::Solid)); let trace2 = Scatter::new(vec![1, 2, 3, 4, 5], vec![6, 8, 7, 8, 6]) .mode(Mode::LinesMarkers) .name("dashdot") .line(Line::new().dash(DashType::DashDot)); let trace3 = Scatter::new(vec![1, 2, 3, 4, 5], vec![11, 13, 12, 13, 11]) .mode(Mode::LinesMarkers) .name("dash") .line(Line::new().dash(DashType::Dash)); let trace4 = Scatter::new(vec![1, 2, 3, 4, 5], vec![16, 18, 17, 18, 16]) .mode(Mode::LinesMarkers) .name("dot") .line(Line::new().dash(DashType::Dot)); let trace5 = Scatter::new(vec![1, 2, 3, 4, 5], vec![21, 23, 22, 23, 21]) .mode(Mode::LinesMarkers) .name("longdash") .line(Line::new().dash(DashType::LongDash)); let trace6 = Scatter::new(vec![1, 2, 3, 4, 5], vec![26, 28, 27, 28, 26]) .mode(Mode::LinesMarkers) .name("longdashdot") .line(Line::new().dash(DashType::LongDashDot)); let mut plot = Plot::new(); let layout = Layout::new() .legend( Legend::new() .y(0.5) .trace_order("reversed") .font(Font::new().size(16)), ) .x_axis(Axis::new().range(vec![0.95, 5.05]).auto_range(false)) .y_axis(Axis::new().range(vec![0.0, 28.5]).auto_range(false)); plot.set_layout(layout); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); plot.add_trace(trace5); plot.add_trace(trace6); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("line_dash"))); } }
Filled Lines
#![allow(unused_variables)] fn main() { fn filled_lines(show: bool) { let x1 = vec![ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, ]; let x2 = (1..=10).map(|iv| iv as f64).collect::<Vec<f64>>(); let trace1 = Scatter::new( x1.clone(), vec![ 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0, ], ) .fill(Fill::ToZeroX) .fill_color(Rgba::new(0, 100, 80, 0.2)) .line(Line::new().color(NamedColor::Transparent)) .name("Fair") .show_legend(false); let trace2 = Scatter::new( x1.clone(), vec![ 5.5, 3.0, 5.5, 8.0, 6.0, 3.0, 8.0, 5.0, 6.0, 5.5, 4.75, 5.0, 4.0, 7.0, 2.0, 4.0, 7.0, 4.4, 2.0, 4.5, ], ) .fill(Fill::ToZeroX) .fill_color(Rgba::new(0, 176, 246, 0.2)) .line(Line::new().color(NamedColor::Transparent)) .name("Premium") .show_legend(false); let trace3 = Scatter::new( x1.clone(), vec![ 11.0, 9.0, 7.0, 5.0, 3.0, 1.0, 3.0, 5.0, 3.0, 1.0, -1.0, 1.0, 3.0, 1.0, -0.5, 1.0, 3.0, 5.0, 7.0, 9.0, ], ) .fill(Fill::ToZeroX) .fill_color(Rgba::new(231, 107, 243, 0.2)) .line(Line::new().color(NamedColor::Transparent)) .name("Fair") .show_legend(false); let trace4 = Scatter::new( x2.clone(), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0], ) .line(Line::new().color(Rgb::new(0, 100, 80))) .name("Fair"); let trace5 = Scatter::new( x2.clone(), vec![5.0, 2.5, 5.0, 7.5, 5.0, 2.5, 7.5, 4.5, 5.5, 5.0], ) .line(Line::new().color(Rgb::new(0, 176, 246))) .name("Premium"); let trace6 = Scatter::new( x2.clone(), vec![10.0, 8.0, 6.0, 4.0, 2.0, 0.0, 2.0, 4.0, 2.0, 0.0], ) .line(Line::new().color(Rgb::new(231, 107, 243))) .name("Ideal"); let layout = Layout::new() .paper_background_color(Rgb::new(255, 255, 255)) .plot_background_color(Rgb::new(229, 229, 229)) .x_axis( Axis::new() .grid_color(Rgb::new(255, 255, 255)) .range(vec![1.0, 10.0]) .show_grid(true) .show_line(false) .show_tick_labels(true) .tick_color(Rgb::new(127, 127, 127)) .ticks(TicksDirection::Outside) .zero_line(false), ) .y_axis( Axis::new() .grid_color(Rgb::new(255, 255, 255)) .show_grid(true) .show_line(false) .show_tick_labels(true) .tick_color(Rgb::new(127, 127, 127)) .ticks(TicksDirection::Outside) .zero_line(false), ); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); plot.add_trace(trace5); plot.add_trace(trace6); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("filled_lines"))); } }
Bar Charts
The following imports have been used to produce the plots below:
#![allow(unused_variables)] fn main() { use plotly::common::{ DashType, ErrorData, ErrorType, Fill, Font, Line, LineShape, Marker, Mode, Title, }; use plotly::layout::{Axis, Layout, Legend, TicksDirection}; use plotly::{NamedColor, Plot, Rgb, Rgba, Scatter}; use rand_distr::{Distribution, Normal}; use itertools; use itertools_num::linspace; }
The to_inline_html method is used to produce the html plot displayed in this page.
Basic Bar Chart
#![allow(unused_variables)] fn main() { fn basic_bar_chart(show: bool) { let animals = vec!["giraffes", "orangutans", "monkeys"]; let t = Bar::new(animals, vec![20, 14, 23]); let mut plot = Plot::new(); plot.add_trace(t); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("basic_bar_chart"))); } }
Grouped Bar Chart
#![allow(unused_variables)] fn main() { fn grouped_bar_chart(show: bool) { let animals1 = vec!["giraffes", "orangutans", "monkeys"]; let trace1 = Bar::new(animals1, vec![20, 14, 23]).name("SF Zoo"); let animals2 = vec!["giraffes", "orangutans", "monkeys"]; let trace2 = Bar::new(animals2, vec![12, 18, 29]).name("LA Zoo"); let layout = Layout::new().bar_mode(BarMode::Group); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("grouped_bar_chart"))); } }
Stacked Bar Chart
#![allow(unused_variables)] fn main() { fn stacked_bar_chart(show: bool) { let animals1 = vec!["giraffes", "orangutans", "monkeys"]; let trace1 = Bar::new(animals1, vec![20, 14, 23]).name("SF Zoo"); let animals2 = vec!["giraffes", "orangutans", "monkeys"]; let trace2 = Bar::new(animals2, vec![12, 18, 29]).name("LA Zoo"); let layout = Layout::new().bar_mode(BarMode::Stack); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("stacked_bar_chart"))); } }
Statistical Charts
| Kind | Link |
|---|---|
| Error Bars | ![]() |
| Box Plots | ![]() |
| Histograms | ![]() |
Error Bars
Basic Symmetric Error Bars
#![allow(unused_variables)] fn main() { fn basic_symmetric_error_bars(show: bool) { let trace1 = Scatter::new(vec![0, 1, 2], vec![6, 10, 2]) .name("trace1") .error_y(ErrorData::new(ErrorType::Data).array(vec![1.0, 2.0, 3.0])); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("basic_symmetric_error_bars")) ); } }
Asymmetric Error Bars
#![allow(unused_variables)] fn main() { fn asymmetric_error_bars(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![2, 1, 3, 4]) .name("trace1") .error_y( ErrorData::new(ErrorType::Data) .array(vec![0.1, 0.2, 0.1, 0.1]) .array_minus(vec![0.2, 0.4, 1., 0.2]), ); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("asymmetric_error_bars"))); } }
Error Bars as a Percentage of the Y Value
#![allow(unused_variables)] fn main() { fn error_bars_as_a_percentage_of_the_y_value(show: bool) { let trace1 = Scatter::new(vec![0, 1, 2], vec![6, 10, 2]) .name("trace1") .error_y(ErrorData::new(ErrorType::Percent).value(50.).visible(true)); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("error_bars_as_a_percentage_of_the_y_value")) ); } }
Asymmetric Error Bars with a Constant Offset
#![allow(unused_variables)] fn main() { fn asymmetric_error_bars_with_a_constant_offset(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![2, 1, 3, 4]) .name("trace1") .error_y( ErrorData::new(ErrorType::Percent) .symmetric(false) .value(15.) .value_minus(25.), ); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("asymmetric_error_bars_with_a_constant_offset")) ); } }
Horizontal Error Bars
#![allow(unused_variables)] fn main() { fn horizontal_error_bars(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![2, 1, 3, 4]) .name("trace1") .error_x(ErrorData::new(ErrorType::Percent).value(10.)); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("horizontal_error_bars"))); } }
Bar Chart with Error Bars
#![allow(unused_variables)] fn main() { fn bar_chart_with_error_bars(show: bool) { let trace_c = Bar::new(vec!["Trial 1", "Trial 2", "Trial 3"], vec![3, 6, 4]) .error_y(ErrorData::new(ErrorType::Data).array(vec![1., 0.5, 1.5])); let trace_e = Bar::new(vec!["Trial 1", "Trial 2", "Trial 3"], vec![4, 7, 3]) .error_y(ErrorData::new(ErrorType::Data).array(vec![0.5, 1., 2.])); let mut plot = Plot::new(); plot.add_trace(trace_c); plot.add_trace(trace_e); let layout = Layout::new().bar_mode(BarMode::Group); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("bar_chart_with_error_bars"))); } }
Colored and Styled Error Bars
#![allow(unused_variables)] fn main() { fn colored_and_styled_error_bars(show: bool) { let x_theo: Vec<f64> = linspace(-4., 4., 100).collect(); let sincx: Vec<f64> = x_theo .iter() .map(|x| (x * std::f64::consts::PI).sin() / (*x * std::f64::consts::PI)) .collect(); let x = vec![ -3.8, -3.03, -1.91, -1.46, -0.89, -0.24, -0.0, 0.41, 0.89, 1.01, 1.91, 2.28, 2.79, 3.56, ]; let y = vec![ -0.02, 0.04, -0.01, -0.27, 0.36, 0.75, 1.03, 0.65, 0.28, 0.02, -0.11, 0.16, 0.04, -0.15, ]; let trace1 = Scatter::new(x_theo, sincx).name("sinc(x)"); let trace2 = Scatter::new(x, y) .mode(Mode::Markers) .name("measured") .error_y( ErrorData::new(ErrorType::Constant) .value(0.1) .color(NamedColor::Purple) .thickness(1.5) .width(3), ) .error_x( ErrorData::new(ErrorType::Constant) .value(0.2) .color(NamedColor::Purple) .thickness(1.5) .width(3), ) .marker(Marker::new().color(NamedColor::Purple).size(8)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("colored_and_styled_error_bars")) ); } }
Box Plots
Basic Box Plot
#![allow(unused_variables)] fn main() { fn basic_box_plot(show: bool) { let mut rng = rand::thread_rng(); let uniform1 = Uniform::new(0.0, 1.0); let uniform2 = Uniform::new(1.0, 2.0); let n = 50; let mut y0 = Vec::with_capacity(n); let mut y1 = Vec::with_capacity(n); for _ in 0..n { y0.push(uniform1.sample(&mut rng)); y1.push(uniform2.sample(&mut rng)); } let trace1 = BoxPlot::<f64, f64>::new(y0); let trace2 = BoxPlot::<f64, f64>::new(y1); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("basic_box_plot")) ); } }
Box Plot that Displays the Underlying Data
#![allow(unused_variables)] fn main() { fn box_plot_that_displays_the_underlying_data(show: bool) { let trace1 = BoxPlot::new(vec![0, 1, 1, 2, 3, 5, 8, 13, 21]) .box_points(BoxPoints::All) .jitter(0.3) .point_pos(-1.8); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("box_plot_that_displays_the_underlying_data")) ); } }
Horizontal Box Plot
#![allow(unused_variables)] fn main() { fn horizontal_box_plot(show: bool) { let trace1 = BoxPlot::new(vec![1, 2, 3, 4, 4, 4, 8, 9, 10]).name("Set 1"); let trace2 = BoxPlot::new(vec![2, 3, 3, 3, 3, 5, 6, 6, 7]).name("Set 2"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("horizontal_box_plot")) ); } }
Grouped Box Plot
#![allow(unused_variables)] fn main() { fn grouped_box_plot(show: bool) { let x = vec![ "day 1", "day 1", "day 1", "day 1", "day 1", "day 1", "day 2", "day 2", "day 2", "day 2", "day 2", "day 2", ]; let trace1 = BoxPlot::new_xy( x.clone(), vec![0.2, 0.2, 0.6, 1.0, 0.5, 0.4, 0.2, 0.7, 0.9, 0.1, 0.5, 0.3], ); let trace2 = BoxPlot::new_xy( x.clone(), vec![0.6, 0.7, 0.3, 0.6, 0.0, 0.5, 0.7, 0.9, 0.5, 0.8, 0.7, 0.2], ); let trace3 = BoxPlot::new_xy( x.clone(), vec![0.1, 0.3, 0.1, 0.9, 0.6, 0.6, 0.9, 1.0, 0.3, 0.6, 0.8, 0.5], ); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); let layout = Layout::new() .y_axis( Axis::new() .title(Title::new("normalized moisture")) .zero_line(false), ) .box_mode(BoxMode::Group); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("grouped_box_plot")) ); } }
Box Plot Styling Outliers
#![allow(unused_variables)] fn main() { fn box_plot_styling_outliers(show: bool) { let y = vec![ 0.75, 5.25, 5.5, 6.0, 6.2, 6.6, 6.80, 7.0, 7.2, 7.5, 7.5, 7.75, 8.15, 8.15, 8.65, 8.93, 9.2, 9.5, 10.0, 10.25, 11.5, 12.0, 16.0, 20.90, 22.3, 23.25, ]; let trace1 = BoxPlot::new(y.clone()) .name("All Points") .jitter(0.3) .point_pos(-1.8) .marker(Marker::new().color(Rgb::new(7, 40, 89))) .box_points(BoxPoints::All); let trace2 = BoxPlot::new(y.clone()) .name("Only Whiskers") .marker(Marker::new().color(Rgb::new(9, 56, 125))) .box_points(BoxPoints::False); let trace3 = BoxPlot::new(y.clone()) .name("Suspected Outlier") .marker( Marker::new() .color(Rgb::new(8, 81, 156)) .outlier_color(Rgba::new(219, 64, 82, 0.6)) .line( Line::new() .outlier_color(Rgba::new(219, 64, 82, 1.0)) .outlier_width(2), ), ) .box_points(BoxPoints::SuspectedOutliers); let trace4 = BoxPlot::new(y.clone()) .name("Whiskers and Outliers") .marker(Marker::new().color(Rgb::new(107, 174, 214))) .box_points(BoxPoints::Outliers); let layout = Layout::new().title(Title::new("Box Plot Styling Outliers")); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("box_plot_styling_outliers")) ); } }
Box Plot Styling Mean and Standard Deviation
#![allow(unused_variables)] fn main() { fn box_plot_styling_mean_and_standard_deviation(show: bool) { let y = vec![ 2.37, 2.16, 4.82, 1.73, 1.04, 0.23, 1.32, 2.91, 0.11, 4.51, 0.51, 3.75, 1.35, 2.98, 4.50, 0.18, 4.66, 1.30, 2.06, 1.19, ]; let trace1 = BoxPlot::new(y.clone()) .name("Only Mean") .marker(Marker::new().color(Rgb::new(8, 81, 156))) .box_mean(BoxMean::True); let trace2 = BoxPlot::new(y.clone()) .name("Mean and Standard Deviation") .marker(Marker::new().color(Rgb::new(8, 81, 156))) .box_mean(BoxMean::StandardDeviation); let layout = Layout::new().title(Title::new("Box Plot Styling Mean and Standard Deviation")); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace1); plot.add_trace(trace2); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("box_plot_styling_mean_and_standard_deviation")) ); } }
Grouped Horizontal Box Plot
#![allow(unused_variables)] fn main() { fn grouped_horizontal_box_plot(show: bool) { let x = vec![ "day 1", "day 1", "day 1", "day 1", "day 1", "day 1", "day 2", "day 2", "day 2", "day 2", "day 2", "day 2", ]; let trace1 = BoxPlot::new_xy( vec![0.2, 0.2, 0.6, 1.0, 0.5, 0.4, 0.2, 0.7, 0.9, 0.1, 0.5, 0.3], x.clone(), ) .name("Kale") .marker(Marker::new().color("3D9970")) .box_mean(BoxMean::False) .orientation(Orientation::Horizontal); let trace2 = BoxPlot::new_xy( vec![0.6, 0.7, 0.3, 0.6, 0.0, 0.5, 0.7, 0.9, 0.5, 0.8, 0.7, 0.2], x.clone(), ) .name("Radishes") .marker(Marker::new().color("FF4136")) .box_mean(BoxMean::False) .orientation(Orientation::Horizontal); let trace3 = BoxPlot::new_xy( vec![0.1, 0.3, 0.1, 0.9, 0.6, 0.6, 0.9, 1.0, 0.3, 0.6, 0.8, 0.5], x.clone(), ) .name("Carrots") .marker(Marker::new().color("FF851B")) .box_mean(BoxMean::False) .orientation(Orientation::Horizontal); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); let layout = Layout::new() .title(Title::new("Grouped Horizontal Box Plot")) .x_axis( Axis::new() .title(Title::new("normalized moisture")) .zero_line(false), ) .box_mode(BoxMode::Group); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("grouped_horizontal_box_plot")) ); } }
Fully Styled Box Plot
#![allow(unused_variables)] fn main() { fn fully_styled_box_plot(show: bool) { let rnd_sample = |num, mul| -> Vec<f64> { let mut v: Vec<f64> = Vec::with_capacity(num); let mut rng = rand::thread_rng(); let uniform = Uniform::new(0.0, mul); for _ in 0..num { v.push(uniform.sample(&mut rng)); } v }; let x_data = vec![ "Carmelo<br>Anthony", "Dwyane<br>Wade", "Deron<br>Williams", "Brook<br>Lopez", "Damian<br>Lillard", "David<br>West", "Blake<br>Griffin", "David<br>Lee", "Demar<br>Derozan", ]; let y_data = vec![ rnd_sample(30, 10.0), rnd_sample(30, 20.0), rnd_sample(30, 25.0), rnd_sample(30, 40.0), rnd_sample(30, 45.0), rnd_sample(30, 30.0), rnd_sample(30, 20.0), rnd_sample(30, 15.0), rnd_sample(30, 43.0), ]; let mut plot = Plot::new(); let layout = Layout::new() .title(Title::new( "Points Scored by the Top 9 Scoring NBA Players in 2012", )) .y_axis( Axis::new() .auto_range(true) .show_grid(true) .zero_line(true) .dtick(5.0) .grid_color(Rgb::new(255, 255, 255)) .grid_width(1) .zero_line_color(Rgb::new(255, 255, 255)) .zero_line_width(2), ) .margin(Margin::new().left(40).right(30).bottom(80).top(100)) .paper_background_color(Rgb::new(243, 243, 243)) .plot_background_color(Rgb::new(243, 243, 243)) .show_legend(false); plot.set_layout(layout); for index in 0..x_data.len() { let trace = BoxPlot::new(y_data[index].clone()) .name(x_data[index]) .box_points(BoxPoints::All) .jitter(0.5) .whisker_width(0.2) .marker(Marker::new().size(6)) .line(Line::new().width(2.0)); plot.add_trace(trace); } if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("fully_styled_box_plot")) ); } }
Histograms
Basic Histogram
#![allow(unused_variables)] fn main() { fn basic_histogram(show: bool) { let samples = sample_normal_distribution(10_000, 0.0, 1.0); let trace = Histogram::new(samples).name("h"); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("basic_histogram")) ); } }
Horizontal Histogram
#![allow(unused_variables)] fn main() { fn horizontal_histogram(show: bool) { let samples = sample_normal_distribution(10_000, 0.0, 1.0); let trace = Histogram::new_horizontal(samples) .name("h") .marker(Marker::new().color(NamedColor::Pink)); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("horizontal_histogram")) ); } }
Overlaid Histogram
#![allow(unused_variables)] fn main() { fn overlaid_histogram(show: bool) { let samples1 = sample_normal_distribution(500, 0.0, 1.0); let trace1 = Histogram::new(samples1) .name("trace 1") .opacity(0.5) .marker(Marker::new().color(NamedColor::Green)); let samples2 = sample_normal_distribution(500, 0.0, 1.0); let trace2 = Histogram::new(samples2) .name("trace 2") .opacity(0.6) .marker(Marker::new().color(NamedColor::Red)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new().bar_mode(BarMode::Overlay); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("overlaid_histogram")) ); } }
Stacked Histograms
#![allow(unused_variables)] fn main() { fn stacked_histograms(show: bool) { let samples1 = sample_normal_distribution(500, 0.0, 1.0); let trace1 = Histogram::new(samples1) .name("trace 1") .opacity(0.5) .marker(Marker::new().color(NamedColor::Green)); let samples2 = sample_normal_distribution(500, 0.0, 1.0); let trace2 = Histogram::new(samples2) .name("trace 2") .opacity(0.6) .marker(Marker::new().color(NamedColor::Red)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new().bar_mode(BarMode::Stack); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("stacked_histograms")) ); } }
Colored and Styled Histograms
#![allow(unused_variables)] fn main() { fn colored_and_styled_histograms(show: bool) { let n = 500; let x1 = sample_uniform_distribution(n, 0.0, 5.0); let x2 = sample_uniform_distribution(n, 0.0, 10.0); let y1 = sample_uniform_distribution(n, 0.0, 1.0); let y2 = sample_uniform_distribution(n, 0.0, 2.0); let trace1 = Histogram::new_xy(x1, y1) .name("control") .hist_func(HistFunc::Count) .marker( Marker::new() .color(Rgba::new(255, 100, 102, 0.7)) .line(Line::new().color(Rgba::new(255, 100, 102, 1.0)).width(1.0)), ) .opacity(0.5) .auto_bin_x(false) .x_bins(Bins::new(0.5, 2.8, 0.06)); let trace2 = Histogram::new_xy(x2, y2) .name("experimental") .hist_func(HistFunc::Count) .marker( Marker::new() .color(Rgba::new(100, 200, 102, 0.7)) .line(Line::new().color(Rgba::new(100, 200, 102, 1.0)).width(1.0)), ) .opacity(0.75) .auto_bin_x(false) .x_bins(Bins::new(-3.2, 4.0, 0.06)); let layout = Layout::new() .title(Title::new("Sampled Results")) .x_axis(Axis::new().title(Title::new("Value"))) .y_axis(Axis::new().title(Title::new("Count"))) .bar_mode(BarMode::Overlay) .bar_gap(0.05) .bar_group_gap(0.2); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace1); plot.add_trace(trace2); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("colored_and_styled_histograms")) ); } }
Cumulative Histogram
#![allow(unused_variables)] fn main() { fn cumulative_histogram(show: bool) { let n = 500; let x = sample_uniform_distribution(n, 0.0, 1.0); let trace = Histogram::new(x) .cumulative(Cumulative::new().enabled(true)) .marker(Marker::new().color(NamedColor::BurlyWood)); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("cumulative_histogram")) ); } }
Normalized Histogram
#![allow(unused_variables)] fn main() { fn normalized_histogram(show: bool) { let n = 500; let x = sample_uniform_distribution(n, 0.0, 1.0); let trace = Histogram::new(x) .hist_norm(HistNorm::Probability) .marker(Marker::new().color(NamedColor::SeaGreen)); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("normalized_histogram")) ); } }
Specify Binning Function
#![allow(unused_variables)] fn main() { fn specify_binning_function(show: bool) { let x = vec!["Apples", "Apples", "Apples", "Organges", "Bananas"]; let y = vec!["5", "10", "3", "10", "5"]; let trace1 = Histogram::new_xy(x.clone(), y.clone()) .name("count") .hist_func(HistFunc::Count); let trace2 = Histogram::new_xy(x.clone(), y.clone()) .name("sum") .hist_func(HistFunc::Sum); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("specify_binning_function")) ); } }
Scientific Charts
| Kind | Link |
|---|---|
| Contour Plots | ![]() |
| Heatmaps | ![]() |
Contour Plots
Simple Contour Plot
#![allow(unused_variables)] fn main() { fn simple_contour_plot(show: bool) { let n = 200; let mut x = Vec::<f64>::new(); let mut y = Vec::<f64>::new(); let mut z: Vec<Vec<f64>> = Vec::new(); for index in 0..n { let value = -2.0 * PI + 4.0 * PI * (index as f64) / (n as f64); x.push(value); y.push(value); } for xi in 0..n { let mut row = Vec::<f64>::new(); for yi in 0..n { let radius_squared = x[xi].powf(2.0) + y[yi].powf(2.0); let zv = x[xi].sin() * y[yi].cos() * radius_squared.sin() / (radius_squared + 1.0).log10(); row.push(zv); } z.push(row); } let trace = Contour::new(x, y, z); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("simple_contour_plot"))); } }
Colorscale for Contour Plot
#![allow(unused_variables)] fn main() { fn colorscale_for_contour_plot(show: bool) { let z = vec![ vec![10.0, 10.625, 12.5, 15.625, 20.0], vec![5.625, 6.25, 8.125, 11.25, 15.625], vec![2.5, 3.125, 5., 8.125, 12.5], vec![0.625, 1.25, 3.125, 6.25, 10.625], vec![0.0, 0.625, 2.5, 5.625, 10.0], ]; let trace = Contour::new_z(z).color_scale(ColorScale::Palette(ColorScalePalette::Jet)); let layout = Layout::new().title(Title::new("Colorscale for Contour Plot")); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("colorscale_for_contour_plot")) ); } }
Customizing Size and Range of a Contour Plot Contours
#![allow(unused_variables)] fn main() { fn customizing_size_and_range_of_a_contour_plots_contours(show: bool) { let z = vec![ vec![10.0, 10.625, 12.5, 15.625, 20.0], vec![5.625, 6.25, 8.125, 11.25, 15.625], vec![2.5, 3.125, 5., 8.125, 12.5], vec![0.625, 1.25, 3.125, 6.25, 10.625], vec![0.0, 0.625, 2.5, 5.625, 10.0], ]; let trace = Contour::new_z(z) .color_scale(ColorScale::Palette(ColorScalePalette::Jet)) .auto_contour(false) .contours(Contours::new().start(0.0).end(8.0).size(2)); let layout = Layout::new().title(Title::new("Customizing Size and Range of Contours")); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some( "customizing_size_and_range_of_a_contour_plots_contours" )) ); } }
Customizing Spacing Between X and Y Ticks
#![allow(unused_variables)] fn main() { fn customizing_spacing_between_x_and_y_ticks(show: bool) { let z = vec![ vec![10.0, 10.625, 12.5, 15.625, 20.0], vec![5.625, 6.25, 8.125, 11.25, 15.625], vec![2.5, 3.125, 5., 8.125, 12.5], vec![0.625, 1.25, 3.125, 6.25, 10.625], vec![0.0, 0.625, 2.5, 5.625, 10.0], ]; let trace = Contour::new_z(z) .color_scale(ColorScale::Palette(ColorScalePalette::Jet)) .dx(10.0) .x0(5.0) .dy(10.0) .y0(10.0); let layout = Layout::new().title(Title::new("Customizing Size and Range of Contours")); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("customizing_spacing_between_x_and_y_ticks")) ); } }
Heatmaps
Basic Heatmap
#![allow(unused_variables)] fn main() { fn basic_heat_map(show: bool) { let z = vec![vec![1, 20, 30], vec![20, 1, 60], vec![30, 60, 1]]; let trace = HeatMap::new_z(z); let mut plot = Plot::new(); plot.add_trace(trace); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("basic_heat_map"))); } }
Financial Charts
| Kind | Link |
|---|---|
| Time Series and Date Axes | ![]() |
| Candlestick Charts | ![]() |
| OHLC Charts | ![]() |
Time Series and Date Axes
Time Series Plot with Custom Date Range
#![allow(unused_variables)] fn main() { fn time_series_plot_with_custom_date_range(show: bool) { let data = load_apple_data(); let date = data.iter().map(|d| d.date.clone()).collect(); let high = data.iter().map(|d| d.high).collect(); let trace = Scatter::new(date, high); let mut plot = Plot::new(); plot.add_trace(trace); let layout = Layout::new() .x_axis(Axis::new().range(vec!["2016-07-01", "2016-12-31"])) .title(Title::new("Manually Set Date Range")); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("time_series_plot_with_custom_date_range")) ); } }
Time Series with Range Slider
#![allow(unused_variables)] fn main() { fn time_series_with_range_slider(show: bool) { let data = load_apple_data(); let date = data.iter().map(|d| d.date.clone()).collect(); let high = data.iter().map(|d| d.high).collect(); let trace = Scatter::new(date, high); let mut plot = Plot::new(); plot.add_trace(trace); let layout = Layout::new() .x_axis(Axis::new().range_slider(RangeSlider::new().visible(true))) .title(Title::new("Manually Set Date Range")); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("time_series_with_range_slider")) ); } }
Time Series with Range Selector Buttons
#![allow(unused_variables)] fn main() { fn time_series_with_range_selector_buttons(show: bool) { let data = load_apple_data(); let date = data.iter().map(|d| d.date.clone()).collect(); let high = data.iter().map(|d| d.high).collect(); let trace = Scatter::new(date, high); let mut plot = Plot::new(); plot.add_trace(trace); let layout = Layout::new().x_axis( Axis::new() .range_slider(RangeSlider::new().visible(true)) .range_selector(RangeSelector::new().buttons(vec![ SelectorButton::new() .count(1) .label("1m") .step(SelectorStep::Month) .step_mode(StepMode::Backward), SelectorButton::new() .count(6) .label("6m") .step(SelectorStep::Month) .step_mode(StepMode::Backward), SelectorButton::new() .count(1) .label("YTD") .step(SelectorStep::Year) .step_mode(StepMode::ToDate), SelectorButton::new() .count(1) .label("1y") .step(SelectorStep::Year) .step_mode(StepMode::Backward), SelectorButton::new().step(SelectorStep::All), ])), ); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("time_series_with_range_selector_buttons")) ); } }
Customizing Tick Label Formatting by Zoom Level
#![allow(unused_variables)] fn main() { fn customizing_tick_label_formatting_by_zoom_level(show: bool) { let data = load_apple_data(); let date = data.iter().map(|d| d.date.clone()).collect(); let high = data.iter().map(|d| d.high).collect(); let trace = Scatter::new(date, high); let mut plot = Plot::new(); plot.add_trace(trace); let layout = Layout::new().x_axis( Axis::new() .range_slider(RangeSlider::new().visible(true)) .tick_format_stops(vec![ TickFormatStop::new() .dtick_range(vec![0, 1000]) .value("%H:%M:%S.%L ms"), TickFormatStop::new() .dtick_range(vec![1000, 60000]) .value("%H:%M:%S s"), TickFormatStop::new() .dtick_range(vec![60000, 3600000]) .value("%H:%M m"), TickFormatStop::new() .dtick_range(vec![3600000, 86400000]) .value("%H:%M h"), TickFormatStop::new() .dtick_range(vec![86400000, 604800000]) .value("%e. %b d"), TickFormatStop::new() .dtick_range(vec!["M1", "M12"]) .value("%b '%y M"), ]), ); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("customizing_tick_label_formatting_by_zoom_level")) ); } }
Candlestick Charts
Simple Candlestick Chart
#![allow(unused_variables)] fn main() { fn simple_candlestick_chart(show: bool) { let x = vec![ "2017-01-04", "2017-01-05", "2017-01-06", "2017-01-09", "2017-01-10", "2017-01-11", "2017-01-12", "2017-01-13", "2017-01-17", "2017-01-18", "2017-01-19", "2017-01-20", "2017-01-23", "2017-01-24", "2017-01-25", "2017-01-26", "2017-01-27", "2017-01-30", "2017-01-31", "2017-02-01", "2017-02-02", "2017-02-03", "2017-02-06", "2017-02-07", "2017-02-08", "2017-02-09", "2017-02-10", "2017-02-13", "2017-02-14", "2017-02-15", ]; let open = vec![ 115.849998, 115.919998, 116.779999, 117.949997, 118.769997, 118.739998, 118.900002, 119.110001, 118.339996, 120.0, 119.400002, 120.449997, 120.0, 119.550003, 120.419998, 121.669998, 122.139999, 120.93, 121.150002, 127.029999, 127.980003, 128.309998, 129.130005, 130.539993, 131.350006, 131.649994, 132.460007, 133.080002, 133.470001, 135.520004, ]; let high = vec![ 116.510002, 116.860001, 118.160004, 119.43, 119.379997, 119.93, 119.300003, 119.620003, 120.239998, 120.5, 120.089996, 120.449997, 120.809998, 120.099998, 122.099998, 122.440002, 122.349998, 121.629997, 121.389999, 130.490005, 129.389999, 129.190002, 130.5, 132.089996, 132.220001, 132.449997, 132.940002, 133.820007, 135.089996, 136.270004, ]; let low = vec![ 115.75, 115.809998, 116.470001, 117.940002, 118.300003, 118.599998, 118.209999, 118.809998, 118.220001, 119.709999, 119.370003, 119.730003, 119.769997, 119.5, 120.279999, 121.599998, 121.599998, 120.660004, 120.620003, 127.010002, 127.779999, 128.160004, 128.899994, 130.449997, 131.220001, 131.119995, 132.050003, 132.75, 133.25, 134.619995, ]; let close = vec![ 116.019997, 116.610001, 117.910004, 118.989998, 119.110001, 119.75, 119.25, 119.040001, 120.0, 119.989998, 119.779999, 120.0, 120.080002, 119.970001, 121.879997, 121.940002, 121.949997, 121.629997, 121.349998, 128.75, 128.529999, 129.080002, 130.289993, 131.529999, 132.039993, 132.419998, 132.119995, 133.289993, 135.020004, 135.509995, ]; let trace1 = Candlestick::new(x, open, high, low, close); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("simple_candlestick_chart")) ); } }
OHLC Charts
Simple OHLC Chart
#![allow(unused_variables)] fn main() { fn simple_ohlc_chart(show: bool) { let x = vec![ "2017-01-04", "2017-01-05", "2017-01-06", "2017-01-09", "2017-01-10", "2017-01-11", "2017-01-12", "2017-01-13", "2017-01-17", "2017-01-18", "2017-01-19", "2017-01-20", "2017-01-23", "2017-01-24", "2017-01-25", "2017-01-26", "2017-01-27", "2017-01-30", "2017-01-31", "2017-02-01", "2017-02-02", "2017-02-03", "2017-02-06", "2017-02-07", "2017-02-08", "2017-02-09", "2017-02-10", "2017-02-13", "2017-02-14", "2017-02-15", ]; let open = vec![ 115.849998, 115.919998, 116.779999, 117.949997, 118.769997, 118.739998, 118.900002, 119.110001, 118.339996, 120.0, 119.400002, 120.449997, 120.0, 119.550003, 120.419998, 121.669998, 122.139999, 120.93, 121.150002, 127.029999, 127.980003, 128.309998, 129.130005, 130.539993, 131.350006, 131.649994, 132.460007, 133.080002, 133.470001, 135.520004, ]; let high = vec![ 116.510002, 116.860001, 118.160004, 119.43, 119.379997, 119.93, 119.300003, 119.620003, 120.239998, 120.5, 120.089996, 120.449997, 120.809998, 120.099998, 122.099998, 122.440002, 122.349998, 121.629997, 121.389999, 130.490005, 129.389999, 129.190002, 130.5, 132.089996, 132.220001, 132.449997, 132.940002, 133.820007, 135.089996, 136.270004, ]; let low = vec![ 115.75, 115.809998, 116.470001, 117.940002, 118.300003, 118.599998, 118.209999, 118.809998, 118.220001, 119.709999, 119.370003, 119.730003, 119.769997, 119.5, 120.279999, 121.599998, 121.599998, 120.660004, 120.620003, 127.010002, 127.779999, 128.160004, 128.899994, 130.449997, 131.220001, 131.119995, 132.050003, 132.75, 133.25, 134.619995, ]; let close = vec![ 116.019997, 116.610001, 117.910004, 118.989998, 119.110001, 119.75, 119.25, 119.040001, 120.0, 119.989998, 119.779999, 120.0, 120.080002, 119.970001, 121.879997, 121.940002, 121.949997, 121.629997, 121.349998, 128.75, 128.529999, 129.080002, 130.289993, 131.529999, 132.039993, 132.419998, 132.119995, 133.289993, 135.020004, 135.509995, ]; let trace1 = Ohlc::new(x, open, high, low, close); let mut plot = Plot::new(); plot.add_trace(trace1); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("simple_ohlc_chart")) ); } }
Subplots
| Kind | Link |
|---|---|
| Subplots | ![]() |
| Multiple Axes | ![]() |
Subplots
Simple Subplot
#![allow(unused_variables)] fn main() { fn simple_subplot(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70]) .name("trace2") .x_axis("x2") .y_axis("y2"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new().grid( LayoutGrid::new() .rows(1) .columns(2) .pattern(GridPattern::Independent), ); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("simple_subplot")) ); } }
Custom Sized Subplot
#![allow(unused_variables)] fn main() { fn custom_sized_subplot(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70]) .name("trace2") .x_axis("x2") .y_axis("y2"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new() .x_axis(Axis::new().domain(&[0., 0.7])) .y_axis2(Axis::new().anchor("x2")) .x_axis2(Axis::new().domain(&[0.8, 1.])); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("custom_sized_subplot")) ); } }
Multiple Subplots
#![allow(unused_variables)] fn main() { fn multiple_subplots(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70]) .name("trace2") .x_axis("x2") .y_axis("y2"); let trace3 = Scatter::new(vec![300, 400, 500], vec![600, 700, 800]) .x_axis("x3") .y_axis("y3"); let trace4 = Scatter::new(vec![4000, 5000, 6000], vec![7000, 8000, 9000]) .x_axis("x4") .y_axis("y4"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); let layout = Layout::new().grid( LayoutGrid::new() .rows(2) .columns(2) .pattern(GridPattern::Independent), ); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("multiple_subplots")) ); } }
Stacked Subplots
#![allow(unused_variables)] fn main() { fn stacked_subplots(show: bool) { let trace1 = Scatter::new(vec![0, 1, 2], vec![10, 11, 12]).name("trace1"); let trace2 = Scatter::new(vec![2, 3, 4], vec![100, 110, 120]) .name("trace2") .x_axis("x2") .y_axis("y2"); let trace3 = Scatter::new(vec![3, 4, 5], vec![1000, 1100, 1200]) .x_axis("x3") .y_axis("y3"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); let layout = Layout::new().grid( LayoutGrid::new() .rows(3) .columns(1) .pattern(GridPattern::Independent) .row_order(RowOrder::BottomToTop), ); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("stacked_subplots")) ); } }
Stacked Subplots with Shared X Axis
#![allow(unused_variables)] fn main() { fn stacked_subplots_with_shared_x_axis(show: bool) { let trace1 = Scatter::new(vec![0, 1, 2], vec![10, 11, 12]).name("trace1"); let trace2 = Scatter::new(vec![2, 3, 4], vec![100, 110, 120]) .name("trace2") .y_axis("y2"); let trace3 = Scatter::new(vec![3, 4, 5], vec![1000, 1100, 1200]).y_axis("y3"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); let layout = Layout::new() .y_axis(Axis::new().domain(&[0., 0.33])) .legend(Legend::new().trace_order("reversed")) .y_axis2(Axis::new().domain(&[0.33, 0.66])) .y_axis3(Axis::new().domain(&[0.66, 1.])); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("stacked_subplots_with_shared_x_axis")) ); } }
Multiple Custom Sized Subplots
#![allow(unused_variables)] fn main() { fn multiple_custom_sized_subplots(show: bool) { let trace1 = Scatter::new(vec![1, 2], vec![1, 2]).name("(1,1)"); let trace2 = Scatter::new(vec![1, 2], vec![1, 2]) .name("(1,2,1)") .x_axis("x2") .y_axis("y2"); let trace3 = Scatter::new(vec![1, 2], vec![1, 2]) .name("(1,2,2)") .x_axis("x3") .y_axis("y3"); let trace4 = Scatter::new(vec![1, 2], vec![1, 2]) .name("{(2,1), (2,2)}") .x_axis("x4") .y_axis("y4"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); let layout = Layout::new() .title(Title::new("Multiple Custom Sized Subplots")) .x_axis(Axis::new().domain(&[0., 0.45]).anchor("y1")) .y_axis(Axis::new().domain(&[0.5, 1.]).anchor("x1")) .x_axis2(Axis::new().domain(&[0.55, 1.]).anchor("y2")) .y_axis2(Axis::new().domain(&[0.8, 1.]).anchor("x2")) .x_axis3(Axis::new().domain(&[0.55, 1.]).anchor("y3")) .y_axis3(Axis::new().domain(&[0.5, 0.75]).anchor("x3")) .x_axis4(Axis::new().domain(&[0., 1.]).anchor("y4")) .y_axis4(Axis::new().domain(&[0., 0.45]).anchor("x4")); plot.set_layout(layout); if show { plot.show(); } println!( "{}", plot.to_inline_html(Some("multiple_custom_sized_subplots")) ); } }
Multiple Axes
Two Y Axes
#![allow(unused_variables)] fn main() { fn two_y_axes(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3], vec![40, 50, 60]).name("trace1"); let trace2 = Scatter::new(vec![2, 3, 4], vec![4, 5, 6]) .name("trace2") .y_axis("y2"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); let layout = Layout::new() .title(Title::new("Double Y Axis Example")) .y_axis(Axis::new().title(Title::new("yaxis title"))) .y_axis2( Axis::new() .title(Title::new("yaxis2 title").font(Font::new().color(Rgb::new(148, 103, 189)))) .tick_font(Font::new().color(Rgb::new(148, 103, 189))) .overlaying("y") .side(Side::Right), ); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("two_y_axes"))); } }
Multiple Axes
#![allow(unused_variables)] fn main() { fn multiple_axes(show: bool) { let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); let trace2 = Scatter::new(vec![2, 3, 4], vec![40, 50, 60]) .name("trace2") .y_axis("y2"); let trace3 = Scatter::new(vec![4, 5, 6], vec![40_000, 50_000, 60_000]).y_axis("y3"); let trace4 = Scatter::new(vec![5, 6, 7], vec![400_000, 500_000, 600_000]).y_axis("y4"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); plot.add_trace(trace3); plot.add_trace(trace4); let layout = Layout::new() .title(Title::new("multiple y-axes example")) .width(800) .x_axis(Axis::new().domain(&[0.3, 0.7])) .y_axis( Axis::new() .title(Title::new("yaxis title").font(Font::new().color("#1f77b4"))) .tick_font(Font::new().color("#1f77b4")), ) .y_axis2( Axis::new() .title(Title::new("yaxis2 title").font(Font::new().color("#ff7f0e"))) .tick_font(Font::new().color("#ff7f0e")) .anchor("free") .overlaying("y") .side(Side::Left) .position(0.15), ) .y_axis3( Axis::new() .title(Title::new("yaxis3 title").font(Font::new().color("#d62728"))) .tick_font(Font::new().color("#d62728")) .anchor("x") .overlaying("y") .side(Side::Right), ) .y_axis4( Axis::new() .title(Title::new("yaxis4 title").font(Font::new().color("#9467bd"))) .tick_font(Font::new().color("#9467bd")) .anchor("free") .overlaying("y") .side(Side::Right) .position(0.85), ); plot.set_layout(layout); if show { plot.show(); } println!("{}", plot.to_inline_html(Some("multiple_axes"))); } }












